using System;
using System.Collections.Generic;
using System.Text;
using Google.GData.Calendar;
using Google.GData.Client;
using Google.GData.Extensions;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;


namespace GCalSync.Core
{
    /// <summary>
    /// Translates between google and outlook event types
    /// </summary>    
    class GoBetween
    {
        /// <summary>
        /// Creates new Outlook Appointment and sets values from google calendar entry 
        /// </summary>
        /// <param name="google">Google calendar entry</param>
        /// <param name="outlook">PocketOutlook session</param>
        public static void AddGoogleToOutlook(EventEntry google, ThisApplication session)
        {
            // Create a new appointment item.
            Outlook.AppointmentItem newApp = session.CreateItem(Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;
            
            // Check to see if it was created be for proceding.
            if (newApp != null)
            {
                // Use below function, not properties would be set so
                // update would occur.
                GoogleToOutlook(google, newApp);
            }
        }        
        
        /// <summary>
        /// Set properties on outlook appoinment from google calendar entry
        /// </summary>
        /// <param name="google">Google calendar entry</param>
        /// <param name="outlook">PocketOutlook appointment</param>
        public static void GoogleToOutlook(EventEntry google, Outlook.AppointmentItem outlook)
        {

            //outlook.LastModificationTime

            outlook.Subject = google.Title.Text;

            // the google time is created with the timezone in the parse.
            outlook.Start = google.Times[0].StartTime.ToUniversalTime().ToLocalTime();
            outlook.End = google.Times[0].EndTime.ToUniversalTime().ToLocalTime();

            outlook.Body = google.Content.Content.ToString();
            outlook.Location = google.Locations.Count > 0 ? google.Locations[0].ValueString : string.Empty;

            // Update the outlook properties or create.
            AddCustomField(outlook, "GCalUpdated", google.Updated.ToString("s"));
            AddCustomField(outlook, "GCalID", google.Id.AbsoluteUri);
            AddCustomField(outlook, "LocalUpdated", DateTime.Now.ToString("s"));
            //AddCustomField(outlook, "OrginalEvent", google.OriginalEvent.ToString());


            //TODO: Reoccurance.
            outlook.Save();
        }

        /// <summary>
        /// Creates new Google Calendar entry and sets values from Outlook
        /// </summary>
        /// <param name="outlook">PocketOutlook Appointment</param>
        /// <param name="google">Google Calendar Service</param>
        public static void AddOutlookToGoogle(Outlook.AppointmentItem outlook)
        {
            // Create a new event entry.
            EventEntry newEntry = new EventEntry();
            
            // Use standard function to update details.
            OutlookToGoogle(outlook, newEntry);

        }
        
        /// <summary>
        /// Sets properties on google entry from outlook appointment
        /// </summary>
        /// <param name="outlook">PocketOutlook appointment</param>
        /// <param name="google">Google calendar entry</param>
        public static void OutlookToGoogle(Outlook.AppointmentItem outlook, EventEntry google)
        {

            google.Title = new AtomTextConstruct(AtomTextConstructElementType.Title, outlook.Subject);
            google.Content.Content = outlook.Body;
            google.Authors.Add(new AtomPerson(AtomPersonType.Unknown, "OutlookGCal"));

            if (google.Locations.Count == 0)
            {
                google.Locations.Add(new Where("", "", outlook.Location));
            }
            else
            {
                google.Locations[0] = new Where("", "", outlook.Location);
            }
            When gTimes = new When();
            gTimes.StartTime = outlook.Start.ToUniversalTime();
            gTimes.EndTime = outlook.End.ToUniversalTime();
            google.Times.Insert(0, gTimes);

            EventEntry returned;

            if (google.Id.Uri == null)
            {
                // Perform the insert to google. Capture the returned EventEntry.
                returned = GoogleCalendar.Service.Insert(GoogleCalendar.Uri, google) as EventEntry;
            }
            else
            {
                returned = GoogleCalendar.Service.Update(google) as EventEntry;
            }

            if (returned != null)
            {
                // Update the outlook properties or create.
                AddCustomField(outlook, "GCalID", returned.Id.AbsoluteUri);
                AddCustomField(outlook, "GCalUpdated", returned.Updated.ToString("s"));
                AddCustomField(outlook, "LocalUpdated", DateTime.Now.ToString("s"));

                // Save outlook item.
                outlook.Save();
            }

        }




        /// <summary>
        /// 
        /// </summary>
        /// <param name="ai"></param>
        /// <param name="fieldName"></param>
        /// <param name="fieldValue"></param>
        public static void AddCustomField(Outlook.AppointmentItem ai, string fieldName, string fieldValue)
        {
            Outlook.UserProperty up = ai.UserProperties.Find(fieldName, System.Reflection.Missing.Value);
            if (up == null)
            {
                up = ai.UserProperties.Add(fieldName, Outlook.OlUserPropertyType.olText, true,
                    System.Reflection.Missing.Value);
                // and then add the label
                up.Value = fieldValue;
            }
            else
            {
                up.Value = fieldValue;
            }
            ai.Save();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ai"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static string GetCustomField(Outlook.AppointmentItem ai, string fieldName)
        {
            Outlook.UserProperty up = ai.UserProperties.Find(fieldName, System.Reflection.Missing.Value);
            if (up == null)
                return "";
            else
                return up.Value.ToString();
        }
    }
}
